#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
#include <functional>
#include <string>
#include <atomic>
#include <mutex>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

using namespace std;

class Obj
{
public:
    void print(const string &str)
    {
        std::cout << "str: "  << str << ""<<  "\n" ;
    }

    int m_num  = 0;

};

int m_shareData = 0;        // 共享数据
std::vector<int> vec;
std::mutex m_mutex;         // 互斥锁
std::atomic<Obj*> m_atoObj(new Obj);  // 操作原子变量
std::atomic<int> m_atoInt(8);
std::atomic<bool> m_flag(true);


void f1(int n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "Thread " << n << " executing\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

void f2(int& n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "Thread 2 executing\n";
        ++n;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

int f3(void *arg)
{
    (void)arg;
    std::cout << "Thread 3 executing\n";
    return 0;
}

void workThread()
{
    lock_guard<std::mutex> mutex(m_mutex);
    std::cout <<"workThread Running \n";

    std::this_thread::sleep_for(std::chrono::seconds(1));

    std::cout << "worker thread is done." << std::endl;
}

void anotherWorkThread()
{
    unique_lock<std::mutex> mutex(m_mutex);
    std::cout << "another worker thread is running..." << std::endl;

    // 这里可以写一些需要互斥保护的代码
    std::this_thread::sleep_for(std::chrono::seconds(1));

    std::cout << "another worker thread is done." << std::endl;
    m_mutex.unlock();  // 手动释放锁
}

void func1()
{
    std::lock_guard<std::mutex> mutex(m_mutex);
    for ( int i=0; i<10; i++ )
    {
        vec.push_back(i);
        std::cout << "func1 push " << i << endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    std::cout << "func1 push Finish\n";
}

void func2()
{
    std::lock_guard<std::mutex> mutex(m_mutex);
    for ( int i=10; i<100; i++ )
    {
        vec.push_back(i);
        std::cout << "func2 push " << i << endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    std::cout << "func2 push Finish\n";
}

void readShareThread(int id)
{
    for ( int i=0; i<5; i++ )
    {
        {
            std::lock_guard<std::mutex> guard(m_mutex);
            m_shareData++;
            std::cout << "Worker " << id << " changed shareData: " << m_shareData << endl;
        }
        cout <<"Worker " << id <<" release lock..................\n";
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}


void thread1(int num)
{
    printf("thread1 Start - %d | m_flag.load(): %d\n", num, m_flag.load());
    while( m_flag.load() )
    {
        printf("waiting...\n");
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    printf("thread1 End\n.");
}


void thread2(int num)
{
    printf("thread2 Start - %d | m_flag.load(): %d\n", num, m_flag.load());
    int count = 0;
    while( 1 )
    {
        if ( count == 5 )
        {
            printf("RELEASE THREAD1 LOCK.\n");
            m_flag.store(false);
        }
        count++;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

std::atomic<int> atomicCounter(0);

void incrementCounter() {
    for (int i = 0; i < 10000; ++i) {
        atomicCounter.fetch_add(1);
    }
}


int main()
{
    int n = 0;
    std::thread t1; // t1 is not a thread
    std::thread t2(f1, n + 1); // pass by value
    std::thread t3(f2, std::ref(n)); // pass by reference (引用传递, 内部线程修改)
    std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread
    t2.join();
    t4.join();
    std::cout << "Final value of n is " << n << '\n';

    std::cout << "\n" << endl;

    thread t5;
    t5 = std::thread(f3, &n);
    t5.join();

    std::cout << "\n" << endl;

    Obj obj;
    thread t6(&Obj::print, &obj, "88888888");
    t6.join();
    std::cout << "\n" << endl;

    // 互斥操作临界区数据
//    std::thread t7(func1);
//    t7.join();

//    std::thread t8(func2);
//    t8.join();

    std::cout << "\n" << endl;

//    std::thread t9(readShareThread, 1);
//    t9.join();

//    std::thread t10(readShareThread, 2);
//    t10.join();

    std::cout << "\n" << endl;

    Obj *sobj = static_cast<Obj*>(m_atoObj.load());
    sobj->m_num = 2;
    printf("m_atoObj.load(): %p | sobj: %p\n", m_atoObj.load(), sobj);

    int num = m_atoInt.load();
    printf("num: %d | lockFree:%d\n", num, m_atoInt.is_lock_free());

    printf("\n");


//    std::thread t11(thread1, 1);
//    std::thread t12(thread2, 2);

    std::thread t13(incrementCounter);
    std::thread t14(incrementCounter);

    t13.join();
    t14.join();

    std::cout << "Final Counter Value: " << atomicCounter.load() << std::endl;

    atomicCounter = 1;      // 线程安全

//    t11.join();
//    t12.join();

    return 0;
}
